"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const turf_1 = __importDefault(require("../../../ext/turf"));
const axios_1 = __importDefault(require("axios"));
const configTool_1 = __importDefault(require("../../../com/configTool"));
const readFromDB_1 = __importDefault(require("../Util/readFromDB"));
const readFromNet_1 = __importDefault(require("../Util/readFromNet"));
const saveToDB_1 = __importDefault(require("../Util/saveToDB"));
const saveToFile_1 = __importDefault(require("../Util/saveToFile"));
const initDB_1 = __importDefault(require("../Util/initDB"));
const awaitWrap_1 = __importDefault(require("../../../lib/awaitWrap"));
const TileUtil4326_1 = __importDefault(require("../../../lib/TileTool/TileUtil4326"));
const TileSet_1 = __importDefault(require("../../TileTool/TileSet"));
const readFromDisk_1 = __importDefault(require("../Util/readFromDisk"));
const World = require('./World.json');
let authority_ing = false;
const DBName = 'CesiumWorldTerrain';
const baseUrl = 'https://assets.ion.cesium.com/asset_depot/1/CesiumWorldTerrain/v1.2/';
const ext = '?extensions=octvertexnormals-watermask-metadata&v=1.2.0';
const Cesium = require('cesium/Build/Cesium/index.cjs');
let Authorization = '';
const defaultAccessToken = Cesium.Ion.defaultAccessToken;
let CesiumTerrain = {
    async init() {
        await configTool_1.default.init();
        configTool_1.default.preservableONDB() && await (0, initDB_1.default)(DBName);
    },
    async ionAuthority() {
        if (authority_ing) {
            await new Promise((resolve) => {
                let timer = setInterval(() => {
                    if (!authority_ing) {
                        clearInterval(timer);
                        resolve(null);
                    }
                }, 100);
            });
        }
        else {
            authority_ing = true;
            let [err, data] = await (0, awaitWrap_1.default)(axios_1.default.get('https://api.cesium.com/v1/assets/1/endpoint?access_token=' + defaultAccessToken));
            if (data) {
                data = data.data;
                Authorization = 'Bearer ' + data.accessToken;
                console.log('获取令牌成功', data.accessToken);
            }
            else {
                console.log(Cesium.Ion.defaultAccessToken);
                console.log('获取令牌失败');
            }
            authority_ing = false;
        }
    },
    async getFileBuffer(url) {
        await this.init();
        let err, buffer, dataSource;
        let headers = { 'Authorization': Authorization };
        let relativePath = '\\1\\' + url;
        let fileSavePath = path_1.default.join(configTool_1.default.appBasePath, `temp/fileOut/assets.cesium.com`, relativePath);
        [err, buffer, dataSource] = await (0, readFromDisk_1.default)({ fileSavePath, err, buffer, dataSource });
        [err, buffer, dataSource] = await (0, readFromDB_1.default)({ DBName, relativePath, err, buffer, dataSource });
        if (!buffer) {
            [err, buffer, dataSource] = await (0, readFromNet_1.default)({ url: baseUrl + url + ext, headers, err, buffer, dataSource });
        }
        if (err?.state === 404) {
        }
        else if (err?.state === 503) {
            console.log('请求过于频繁，服务器拒绝响应');
        }
        else if (err?.state === 401) {
            console.log(err);
            console.log('重置 Cesium 地形资源的 令牌');
            Authorization = '';
        }
        buffer && dataSource !== 'DB' && configTool_1.default.preservableONDB() && (0, saveToDB_1.default)({
            DBName,
            relativePath,
            buffer
        }, true).then();
        buffer && dataSource === 'Net' && configTool_1.default.preservableONFile() && (0, saveToFile_1.default)(fileSavePath, buffer).then();
        return [err, buffer];
    },
    async getTileListByGeoJson(zoom, geoJson, layerJson) {
        await this.init();
        const tileUtil4326 = new TileUtil4326_1.default();
        geoJson = geoJson || World;
        if (!layerJson) {
            const [err, buffer] = await CesiumTerrain.getFileBuffer('layer.json');
            layerJson = buffer ? JSON.parse(buffer.toString()) : null;
            if (err || layerJson === null) {
                return { tileList: [], boxList: [] };
            }
        }
        const dataRanges = layerJson.available;
        const tileSet = new TileSet_1.default();
        const boxList = [];
        const areaRangeList = dataRanges[zoom];
        const effectiveAreaRangeList = [];
        for (let i = 0; i < areaRangeList?.length; i++) {
            const rowAreaRange = areaRangeList[i];
            const rowMinTile = tileUtil4326.tileXYZToRectanglePolygon(rowAreaRange.startX, rowAreaRange.startY, zoom);
            const rowMaxTile = tileUtil4326.tileXYZToRectanglePolygon(rowAreaRange.endX, rowAreaRange.endY, zoom);
            const rowAreaBbox = turf_1.default.bbox(turf_1.default.featureCollection([rowMinTile, rowMaxTile]));
            const rowAreaBoxPolygon = turf_1.default.bboxPolygon(rowAreaBbox);
            if (turf_1.default.booleanDisjoint(geoJson, rowAreaBoxPolygon)) {
                continue;
            }
            const polygons = [];
            turf_1.default.featureEach(geoJson, function (currentFeature) {
                if (currentFeature.geometry.type === 'Polygon') {
                    polygons.push(currentFeature.geometry.coordinates);
                }
            });
            const multiPoly = turf_1.default.multiPolygon(polygons);
            const clipGeoJson = turf_1.default.bboxClip(multiPoly, rowAreaBbox);
            const clipBbox = turf_1.default.bbox(clipGeoJson);
            const trimMinTile = tileUtil4326.getTileXYZ(clipBbox[0], clipBbox[1], zoom);
            const trimMaxTile = tileUtil4326.getTileXYZ(clipBbox[2], clipBbox[3], zoom);
            const trimRowAreaRange = {
                endX: Math.min(trimMaxTile.x, rowAreaRange.endX),
                endY: Math.min(trimMaxTile.y, rowAreaRange.endY),
                startX: Math.max(trimMinTile.x, rowAreaRange.startX),
                startY: Math.max(trimMinTile.y, rowAreaRange.startY)
            };
            const middle_1_3_X = trimRowAreaRange.startX + Math.floor((trimRowAreaRange.endX - trimRowAreaRange.startX) / 3) - 1;
            const middle_2_3_X = trimRowAreaRange.startX + Math.floor((trimRowAreaRange.endX - trimRowAreaRange.startX) / 3) * 2 - 1;
            const middle_1_3_Y = trimRowAreaRange.startY + Math.floor((trimRowAreaRange.endY - trimRowAreaRange.startY) / 3) - 1;
            const middle_2_3_Y = trimRowAreaRange.startY + Math.floor((trimRowAreaRange.endY - trimRowAreaRange.startY) / 3) * 2 - 1;
            const leafOne = {
                startX: trimRowAreaRange.startX,
                startY: trimRowAreaRange.startY,
                endX: middle_1_3_X,
                endY: middle_1_3_Y
            };
            const leafTwo = {
                startX: middle_1_3_X + 1,
                startY: trimRowAreaRange.startY,
                endX: middle_2_3_X,
                endY: middle_1_3_Y
            };
            const leafThree = {
                startX: trimRowAreaRange.startX,
                startY: middle_1_3_Y + 1,
                endX: middle_1_3_X,
                endY: middle_2_3_Y
            };
            const leafFour = {
                startX: middle_1_3_X + 1,
                startY: middle_1_3_Y + 1,
                endX: middle_2_3_X,
                endY: middle_2_3_Y
            };
            const leafFive = {
                startX: middle_2_3_X + 1,
                startY: trimRowAreaRange.startY,
                endX: trimRowAreaRange.endX,
                endY: middle_1_3_Y
            };
            const leafSix = {
                startX: middle_2_3_X + 1,
                startY: middle_1_3_Y + 1,
                endX: trimRowAreaRange.endX,
                endY: middle_2_3_Y
            };
            const leafSeven = {
                startX: trimRowAreaRange.startX,
                startY: middle_2_3_Y + 1,
                endX: middle_1_3_X,
                endY: trimRowAreaRange.endY
            };
            const leafEight = {
                startX: middle_2_3_X + 1,
                startY: middle_2_3_Y + 1,
                endX: trimRowAreaRange.endX,
                endY: trimRowAreaRange.endY
            };
            const leafNine = {
                startX: middle_1_3_X + 1,
                startY: middle_2_3_Y + 1,
                endX: middle_2_3_X,
                endY: trimRowAreaRange.endY
            };
            const leafList = [leafOne, leafTwo, leafThree, leafFour, leafFive, leafSix, leafSeven, leafEight, leafNine];
            for (let j = 0; j < leafList.length; j++) {
                const leafAreaRange = leafList[j];
                const minTile = tileUtil4326.tileXYZToRectanglePolygon(leafAreaRange.startX, leafAreaRange.startY, zoom);
                const maxTile = tileUtil4326.tileXYZToRectanglePolygon(leafAreaRange.endX, leafAreaRange.endY, zoom);
                const areaBbox = turf_1.default.bbox(turf_1.default.featureCollection([minTile, maxTile]));
                const areaBoxPolygon = turf_1.default.bboxPolygon(areaBbox);
                if (!turf_1.default.booleanDisjoint(geoJson, areaBoxPolygon)) {
                    const polygons = [];
                    turf_1.default.featureEach(geoJson, function (currentFeature) {
                        if (currentFeature.geometry.type === 'Polygon') {
                            polygons.push(currentFeature.geometry.coordinates);
                        }
                    });
                    const multiPoly = turf_1.default.multiPolygon(polygons);
                    const clipGeoJson = turf_1.default.bboxClip(multiPoly, areaBbox);
                    const clipBbox = turf_1.default.bbox(clipGeoJson);
                    const trimMinTile = tileUtil4326.getTileXYZ(clipBbox[0], clipBbox[1], zoom);
                    const trimMaxTile = tileUtil4326.getTileXYZ(clipBbox[2], clipBbox[3], zoom);
                    const areaRange = {
                        endX: Math.min(trimMaxTile.x, leafAreaRange.endX),
                        endY: Math.min(trimMaxTile.y, leafAreaRange.endY),
                        startX: Math.max(trimMinTile.x, leafAreaRange.startX),
                        startY: Math.max(trimMinTile.y, leafAreaRange.startY)
                    };
                    const areaRangeBox = turf_1.default.bboxPolygon(turf_1.default.bbox(turf_1.default.featureCollection([
                        tileUtil4326.tileXYZToRectanglePolygon(areaRange.startX, areaRange.startY, zoom),
                        tileUtil4326.tileXYZToRectanglePolygon(areaRange.endX, areaRange.endY, zoom)
                    ])));
                    boxList.push(areaRangeBox);
                    effectiveAreaRangeList.push(areaRange);
                    for (let x = areaRange.startX; x <= areaRange.endX; x++) {
                        for (let y = areaRange.startY; y <= areaRange.endY; y++) {
                            tileSet.add(x, y, zoom);
                        }
                    }
                }
            }
        }
        return { tileList: tileSet.getAll(), boxList, effectiveAreaRangeList };
    }
};
exports.default = CesiumTerrain;
